﻿using FastORM.Definition;
using FastORM.Entity;
using FastORM.Mapping;
using FastUtil.Convert;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;

namespace FastORM.Realization
{
    public class DefaultSQLBuild : IFastSQLBuild
    {
        public virtual string BuildCountSQL<T>()
        {
            MapperEntity map = StructMapping.GetInstance().GetMapperEntity(typeof(T));
            return string.Format("select count(1) from {0}", map.TableName);
        }

        public virtual string BuildDeleteSQL<T>(T Entity)
        {
            MapperEntity map = StructMapping.GetInstance().GetMapperEntity(typeof(T));
            return string.Format("delete from {0} where {1}=@{1}", map.TableName, map.KeyName);
        }

        public virtual string BuildDeleteSQL<T>()
        {
            MapperEntity map = StructMapping.GetInstance().GetMapperEntity(typeof(T));
            return string.Format("delete from {0} where {1}=@{1}", map.TableName, map.KeyName);
        }

        public virtual string BuildDeleteSQL<T>(string KeyFieldName)
        {
            MapperEntity map = StructMapping.GetInstance().GetMapperEntity(typeof(T));
            return string.Format("delete from {0} where {1}=@{1}", map.TableName, KeyFieldName);
        }

        public virtual string BuildDeleteSQL(string TableName, string KeyFieldName)
        {
            return string.Format("delete from {0} where {1}=@{1}", TableName, KeyFieldName);
        }

        public string BuildFindSQL<T>()
        {
            MapperEntity map = StructMapping.GetInstance().GetMapperEntity(typeof(T));
            return string.Format("select * from {0} where {1}=@{1}", map.TableName, map.KeyName);
        }

        public virtual string BuildFindSQL<T>(string KeyFieldName)
        {
            MapperEntity map = StructMapping.GetInstance().GetMapperEntity(typeof(T));
            return string.Format("select * from {0} where {1}=@{1}", map.TableName, KeyFieldName);
        }

        public virtual string BuildFindSQL(string TableName, string KeyFieldName)
        {
            return string.Format("select * from {0} where {1}=@{1}", TableName, KeyFieldName);
        }

        public virtual string BuildFindListSQL<T>(string Columns, string Where, string OrderBy)
        {
            MapperEntity map = StructMapping.GetInstance().GetMapperEntity(typeof(T));
            string sql = string.Format("select {0} from {1}", Columns, map.TableName);
            if (!string.IsNullOrEmpty(Where))
            {
                sql += string.Format(" where {0}", Where);
            }
            if (!string.IsNullOrEmpty(OrderBy))
            {
                sql += string.Format(" order by {0}", OrderBy);
            }
            return sql;
        }

        public virtual string BuildFindPageSQL<T>(string Columns, string Where, string OrderBy, int PageIndex, int PageSize)
        {
            throw new NotImplementedException();
        }

        public virtual string BuildInsertSQL<T>(T Entity)
        {
            MapperEntity map = StructMapping.GetInstance().GetMapperEntity(typeof(T));
            StringBuilder buildsql = new StringBuilder();
            buildsql.AppendFormat("insert into {0}", map.TableName);
            //字段
            string fieldsstr = string.Empty;
            //值
            string valuestr = string.Empty;
            fieldsstr += " (";
            valuestr += " values(";
            foreach (var item in map.ColumnMapDic)
            {
                fieldsstr += item.Value + ",";
                valuestr += string.Format("@{0}", item.Value) + ",";
            }
            fieldsstr = fieldsstr.TrimEnd(',') + " )";
            valuestr = valuestr.TrimEnd(',') + " )";
            buildsql.Append(fieldsstr).Append(valuestr);
            return buildsql.ToString();
        }

        public virtual string BuildInsertSQL(string TableName, Hashtable RowData)
        {
            StringBuilder buildsql = new StringBuilder();
            buildsql.AppendFormat("insert into {0}", TableName);
            //字段
            string fieldsstr = string.Empty;
            //值
            string valuestr = string.Empty;
            fieldsstr += " (";
            valuestr += " values(";
            foreach (string key in RowData.Keys)
            {
                fieldsstr += key + ",";
                valuestr += string.Format("@{0}", key) + ",";
            }
            fieldsstr = fieldsstr.TrimEnd(',') + " )";
            valuestr = valuestr.TrimEnd(',') + " )";
            buildsql.Append(fieldsstr).Append(valuestr);
            return buildsql.ToString();
        }

        public virtual string BuildUpdateSQL<T>(T Entity) where T : BaseEntity
        {
            MapperEntity map = StructMapping.GetInstance().GetMapperEntity(typeof(T));
            StringBuilder buildsql = new StringBuilder();
            buildsql.AppendFormat("update {0} set ", map.TableName);
            string tempstr = string.Empty;
            foreach (var item in map.ColumnMapDic)
            {
                //这里判断实体类的具体字段值为null或者dbnull的不更新
                //如果UpdateFieldList包含此字段不管是不是null都更新
                var epv = map.EmitDic[item.Key.Name].EmitGetter(Entity);
                if (Entity.UpdateFieldList.Contains(item.Key.Name))
                {
                    tempstr += string.Format("{0}=@{0},", item.Value);
                }
                else
                {
                    if (epv != null && !Convert.IsDBNull(epv))
                    {
                        tempstr += string.Format("{0}=@{0},", item.Value);
                    }
                }

            }
            tempstr = tempstr.TrimEnd(',');
            buildsql.Append(tempstr);
            buildsql.AppendFormat(" where {0}=@{0}", map.KeyName);
            return buildsql.ToString();
        }

        public virtual string BuildUpdateSQL<T>(T Entity, string[] UpdateFileds) where T : BaseEntity
        {
            MapperEntity map = StructMapping.GetInstance().GetMapperEntity(typeof(T));
            StringBuilder buildsql = new StringBuilder();
            buildsql.AppendFormat("update {0} set ", map.TableName);
            string tempstr = string.Empty;
            List<string> UpdateFiledList = StructConvert.ConvertArrayToList(UpdateFileds);
            foreach (var item in map.ColumnMapDic)
            {
                //根据UpdateFileds指定，无论是否null，强制更新
                //如果UpdateFieldList包含此字段不管是不是null都更新
                var epv = map.EmitDic[item.Key.Name].EmitGetter(Entity);
                if (Entity.UpdateFieldList.Contains(item.Key.Name))
                {
                    tempstr += string.Format("{0}=@{0},", item.Value);
                }
                else
                {
                    if (epv != null && !Convert.IsDBNull(epv) && UpdateFiledList.Contains(item.Value))
                    {
                        tempstr += string.Format("{0}=@{0},", item.Value);
                    }
                }

            }
            tempstr = tempstr.TrimEnd(',');
            buildsql.Append(tempstr);
            buildsql.AppendFormat(" where {0}=@{0}", map.KeyName);
            return buildsql.ToString();
        }

        public virtual string BuildUpdateSQL(string TableName, string KeyFieldName, Hashtable RowData)
        {
            StringBuilder buildsql = new StringBuilder();
            buildsql.AppendFormat("update {0} set ", TableName);
            string tempstr = string.Empty;
            foreach (string key in RowData.Keys)
            {
                tempstr += string.Format("{0}=@{0},", key);
            }
            tempstr = tempstr.TrimEnd(',');
            buildsql.Append(tempstr);
            buildsql.AppendFormat(" where {0}=@{0}", KeyFieldName);
            return buildsql.ToString();
        }

        public virtual string BuildFindPageSQL<T>(string SQL, int PageIndex, int PageSize)
        {
            throw new NotImplementedException();
        }

        public virtual string BuildFindPageSQL(string SQL, int PageIndex, int PageSize)
        {
            throw new NotImplementedException();
        }
    }
}
